import { ModernBaseService } from './base/ModernBaseService';
import { TaskRepository, PlayerTaskData, TaskProgressUpdateResult, TaskCompletionResult, ServerTaskStats } from '../repository/TaskRepository';
import { Task } from '../domain/entities/Task';
import { Player } from '../domain/entities/Player';
import { 
    TaskType, 
    TaskStatus, 
    TaskTargetType, 
    TaskConfig, 
    TaskTarget, 
    TaskReward, 
    PlayerTaskProgress, 
    ServerTaskProgress,
    TaskSystemData,
    RankingData
} from '../core/rpg/types/task';
import { TaskError, TaskNotFoundError, TaskAlreadyCompletedError } from '../domain/errors/TaskError';
import { DIContainer } from '../infrastructure/di';

/**
 * 现代化任务服务类
 * 重构后的任务服务，保持与原功能完全对等
 * 职责：
 * 1. 任务配置管理
 * 2. 玩家任务数据管理
 * 3. 任务进度跟踪和更新
 * 4. 任务完成和奖励发放
 * 5. 世界任务管理
 * 6. 邮件发送状态管理
 */
export class ModernTaskService extends ModernBaseService {
    private taskRepository: TaskRepository;

    constructor(container?: DIContainer) {
        super(container);
        this.taskRepository = new TaskRepository(container);
    }

    /**
     * 服务初始化
     */
    protected async onInit(): Promise<void> {
        await this.taskRepository.init();
        this.log('ModernTaskService initialized successfully');
    }

    /**
     * 服务销毁
     */
    protected async onDestroy(): Promise<void> {
        await this.taskRepository.destroy();
        this.log('ModernTaskService destroyed successfully');
    }

    // ===== 任务配置管理 =====

    /**
     * 获取任务配置
     * @returns 任务配置列表
     */
    async getTaskConfigs(): Promise<TaskConfig[]> {
        return this.cached('task_configs', async () => {
            return await this.taskRepository.getTaskConfigs();
        }, 3600000); // 缓存1小时
    }

    /**
     * 获取特定任务配置
     * @param taskId 任务ID
     * @returns 任务配置
     */
    async getTaskConfig(taskId: string): Promise<TaskConfig | null> {
        const configs = await this.getTaskConfigs();
        return configs.find(config => config.id === taskId) || null;
    }

    // ===== 玩家任务管理 =====

    /**
     * 初始化玩家任务数据
     * @param playerId 玩家ID
     * @returns 任务系统数据
     */
    async initPlayerTaskData(playerId: string): Promise<PlayerTaskData> {
        return this.withPerformanceMonitoring(async () => {
            this.validateRequiredParams({ playerId }, ['playerId']);

            let taskData = await this.taskRepository.getPlayerTaskData(playerId);
            
            // 确保所有任务配置都已添加
            const configs = await this.getTaskConfigs();
            const existingTaskIds = new Set(taskData.playerTasks.map(t => t.id));
            
            // 添加新的任务配置
            for (const config of configs) {
                if (!existingTaskIds.has(config.id)) {
                    const newTask = Task.create({
                        id: config.id,
                        name: config.name,
                        description: config.description,
                        type: config.type,
                        status: TaskStatus.进行中,
                        targets: config.targets.map(target => ({ ...target, current: 0 })),
                        rewards: config.rewards,
                        startTime: config.startTime,
                        endTime: config.endTime,
                        data: config
                    });
                    taskData.playerTasks.push(newTask);
                }
            }

            // 保存更新后的数据
            await this.taskRepository.savePlayerTaskData(playerId, taskData);
            
            return taskData;
        }, 'initPlayerTaskData');
    }

    /**
     * 获取玩家任务列表
     * @param playerId 玩家ID
     * @param status 任务状态过滤
     * @param type 任务类型过滤
     * @returns 任务列表
     */
    async getPlayerTasks(playerId: string, status?: TaskStatus, type?: TaskType): Promise<Task[]> {
        this.validateRequiredParams({ playerId }, ['playerId']);
        
        const taskData = await this.taskRepository.getPlayerTaskData(playerId);
        let tasks = taskData.playerTasks;
        
        if (status) {
            tasks = tasks.filter(task => task.status === status);
        }
        
        if (type) {
            tasks = tasks.filter(task => task.type === type);
        }
        
        return tasks;
    }

    /**
     * 获取玩家世界任务
     * @param playerId 玩家ID
     * @param mapName 地图名称
     * @returns 世界任务列表
     */
    async getPlayerWorldTasks(playerId: string, mapName: string): Promise<TaskConfig[]> {
        this.validateRequiredParams({ playerId, mapName }, ['playerId', 'mapName']);
        return await this.taskRepository.getPlayerWorldTasks(playerId, mapName);
    }

    /**
     * 清理玩家世界任务
     * @param playerId 玩家ID
     * @returns 清理结果
     */
    async clearPlayerWorldTasks(playerId: string): Promise<{
        success: boolean;
        message: string;
    }> {
        return this.withPerformanceMonitoring(async () => {
            this.validateRequiredParams({ playerId }, ['playerId']);

            await this.taskRepository.clearPlayerWorldTasks(playerId);
            
            return {
                success: true,
                message: '世界任务清理成功'
            };
        }, 'clearPlayerWorldTasks');
    }

    // ===== 任务进度管理 =====

    /**
     * 更新任务进度
     * @param playerId 玩家ID
     * @param targetType 目标类型
     * @param targetId 目标ID
     * @param count 增加的数量
     * @returns 更新结果
     */
    async updateTaskProgress(
        playerId: string, 
        targetType: TaskTargetType, 
        targetId?: string, 
        count: number = 1
    ): Promise<TaskProgressUpdateResult> {
        return this.withPerformanceMonitoring(async () => {
            this.validateRequiredParams({ playerId, targetType, count }, ['playerId', 'targetType', 'count']);

            if (count <= 0) {
                throw new Error('Count must be positive');
            }

            const result = await this.taskRepository.updateTaskProgress(playerId, targetType, targetId, count);
            
            // 触发任务更新事件
            if (result.updatedTasks.length > 0) {
                await this.onTasksUpdated(playerId, result.updatedTasks);
            }
            
            if (result.completedTasks.length > 0) {
                await this.onTasksCompleted(playerId, result.completedTasks);
            }

            return result;
        }, 'updateTaskProgress');
    }

    /**
     * 完成任务
     * @param playerId 玩家ID
     * @param taskId 任务ID
     * @returns 完成结果
     */
    async completeTask(playerId: string, taskId: string): Promise<TaskCompletionResult> {
        return this.withPerformanceMonitoring(async () => {
            this.validateRequiredParams({ playerId, taskId }, ['playerId', 'taskId']);

            const result = await this.taskRepository.completeTask(playerId, taskId);
            
            if (result.success && result.task) {
                // 发放奖励
                const rewardResult = await this.grantTaskRewards(playerId, result.rewards);
                
                // 触发任务完成事件
                await this.onTaskCompleted(playerId, result.task, result.rewards);
                
                return {
                    ...result,
                    rewardResult
                };
            }

            return result;
        }, 'completeTask');
    }

    // ===== 奖励管理 =====

    /**
     * 发放任务奖励
     * @param playerId 玩家ID
     * @param rewards 奖励列表
     * @returns 发放结果
     */
    async grantTaskRewards(playerId: string, rewards: TaskReward[]): Promise<RewardResult> {
        return this.withPerformanceMonitoring(async () => {
            const grantedRewards: TaskReward[] = [];
            const failedRewards: { reward: TaskReward; error: string }[] = [];

            for (const reward of rewards) {
                try {
                    await this.grantSingleReward(playerId, reward);
                    grantedRewards.push(reward);
                } catch (error: any) {
                    failedRewards.push({
                        reward,
                        error: (error as any).message
                    });
                }
            }

            return {
                success: failedRewards.length === 0,
                grantedRewards,
                failedRewards,
                message: `成功发放 ${grantedRewards.length}/${rewards.length} 个奖励`
            };
        }, 'grantTaskRewards');
    }

    /**
     * 发放单个奖励
     * @param playerId 玩家ID
     * @param reward 奖励
     */
    private async grantSingleReward(playerId: string, reward: TaskReward): Promise<void> {
        const rewardType = reward.type as string;
        switch (rewardType) {
            case 'item':
                // 发放物品奖励
                await this.grantItemReward(playerId, reward);
                break;
            case 'exp':
                // 发放经验奖励
                await this.grantExpReward(playerId, reward);
                break;
            case 'gold':
                // 发放金币奖励
                await this.grantGoldReward(playerId, reward);
                break;
            default:
                this.log(`Unknown reward type: ${reward.type}`, 'warn');
        }
    }

    /**
     * 发放物品奖励
     */
    private async grantItemReward(playerId: string, reward: TaskReward): Promise<void> {
        // 这里需要与背包服务集成
        const bagService = this.container?.get('ModernBagService');
        if (bagService) {
            await (bagService as any).addItem(playerId, {
                id: reward.id,
                name: reward.name,
                description: '',
                type: 'consumable',
                count: reward.count
            });
        }
    }

    /**
     * 发放经验奖励
     */
    private async grantExpReward(playerId: string, reward: TaskReward): Promise<void> {
        // 这里需要与RPG服务集成
        const rpgService = this.container?.get('ModernRPGService');
        if (rpgService) {
            await (rpgService as any).addExperience(playerId, reward.count, 'task_reward');
        }
    }

    /**
     * 发放金币奖励
     */
    private async grantGoldReward(playerId: string, reward: TaskReward): Promise<void> {
        // 这里需要实现金币系统
        this.log(`Granted ${reward.count} gold to player ${playerId}`);
    }

    // ===== 统计和排行榜 =====

    /**
     * 获取全服任务统计
     * @param taskType 任务类型
     * @returns 统计数据
     */
    async getServerTaskStats(taskType?: TaskType): Promise<ServerTaskStats> {
        return await this.taskRepository.getServerTaskStats(taskType);
    }

    /**
     * 获取排行榜
     * @param type 排行榜类型
     * @param limit 限制数量
     * @returns 排行榜数据
     */
    async getRankingLeaderboard(type: string, limit: number = 10): Promise<RankingData[]> {
        return await this.taskRepository.getRankingData(type, limit);
    }

    // ===== 邮件发送状态管理 =====

    /**
     * 检查邮件发送状态
     * @param taskId 任务ID
     * @returns 是否已发送
     */
    isMailSent(taskId: string): boolean {
        return this.taskRepository.isMailSent(taskId);
    }

    /**
     * 标记邮件已发送
     * @param taskId 任务ID
     */
    markMailAsSent(taskId: string): void {
        this.taskRepository.markMailAsSent(taskId);
    }

    // ===== 私有辅助方法 =====

    /**
     * 检查任务是否可以完成
     */
    private canCompleteTask(task: Task): boolean {
        return task.targets.every(target => (target.current || 0) >= target.count);
    }

    // ===== 事件处理 =====

    /**
     * 任务更新事件处理
     */
    private async onTasksUpdated(playerId: string, tasks: Task[]): Promise<void> {
        this.log(`Player ${playerId} updated ${tasks.length} tasks`);
        
        // 清除相关缓存
        this.clearCache(`task_${playerId}`);
    }

    /**
     * 任务完成事件处理
     */
    private async onTasksCompleted(playerId: string, tasks: Task[]): Promise<void> {
        this.log(`Player ${playerId} completed ${tasks.length} tasks`);
        
        // 清除相关缓存
        this.clearCache(`task_${playerId}`);
        this.clearCache('server_task_stats_all');
    }

    /**
     * 单个任务完成事件处理
     */
    private async onTaskCompleted(playerId: string, task: Task, rewards: TaskReward[]): Promise<void> {
        this.log(`Player ${playerId} completed task ${task.name}, rewards: ${rewards.length}`);
    }
}

// ===== 简化的接口定义 =====

/**
 * 奖励结果接口
 */
export interface RewardResult {
    success: boolean;
    grantedRewards: TaskReward[];
    failedRewards: { reward: TaskReward; error: string }[];
    message: string;
}